#include "bsp_flash.h"
#include <stdint.h>
#include <string.h>
#include "at32f403a_407_flash.h"

uint8_t bsp_flash_read_byte(uint32_t u32Addr, uint8_t *pu8Buffer, uint32_t u32Len){

    // 判断输入参数是否合法
    if(NULL == pu8Buffer || 0 == u32Len || u32Addr < FLASH_BASE_ADDR || 
        u32Addr + u32Len > FLASH_END_ADDR) return 1;

    // 读取数据
    for(uint32_t i = 0; i < u32Len; i++)
    {
        pu8Buffer[i] = *(uint8_t*)(u32Addr);
        u32Addr += 1;
    }

    // 读取成功
    return 0;
}

uint8_t bsp_flash_read_halfword(uint32_t u32Addr, uint16_t *pu16Buffer, uint32_t u32Len){
    
    // 判断输入参数是否合法
    if(NULL == pu16Buffer || 0 == u32Len || u32Addr >= FLASH_BANK2_END_ADDR || u32Addr < FLASH_BANK1_START_ADDR) return 1;

    // 地址对齐
    u32Addr = u32Addr / 2 * 2;

    // 读取数据
    for(uint32_t i = 0; i < u32Len; i++)
    {
        // 获取数据
        uint16_t u16Temp = *(uint16_t*)(u32Addr);

        // 分离高低位 -- 低位在前，高位在后
        uint16_t u16Low = (u16Temp >> 8) & 0x00FF;
        uint16_t u16High = u16Temp & 0x00FF;

        // 存储数据
        pu16Buffer[i] = (u16High << 8) | u16Low;
        u32Addr += 2;
    }

    // 读取成功
    return 0;
}

uint8_t bsp_flash_read_word(uint32_t u32Addr, uint32_t *pu32Buffer, uint32_t u32Len){
    
    // 判断输入参数是否合法
    if(NULL == pu32Buffer || 0 == u32Len || u32Addr >= FLASH_BANK2_END_ADDR || u32Addr < FLASH_BANK1_START_ADDR) return 1;

    // 地址对齐
    u32Addr = u32Addr / 4 * 4;

    // 读取数据
    for(uint32_t i = 0; i < u32Len; i++)
    {
        // 获取数据
        uint32_t u32Temp = *(uint32_t*)(u32Addr);

        // 分离高低位 -- 低位在前，高位在后
        uint32_t u32Low = (u32Temp >> 24) & 0x000000FF;
        uint32_t u32M1 = (u32Temp >> 16) & 0x000000FF;
        uint32_t u32M2 = (u32Temp >> 8) & 0x000000FF;
        uint32_t u32High = (u32Temp ) & 0x000000FF;

        // 存储数据
        pu32Buffer[i] = u32High << 24 | u32M2 << 16 | u32M1 << 8 | u32Low;
        u32Addr += 4;
    }
    // 读取成功
    return 0;
}

uint8_t bsp_flash_erase_sector(uint32_t u32Addr){

    // 判断输入参数是否合法
    if( u32Addr > FLASH_END_ADDR || u32Addr < FLASH_BASE_ADDR) return 1;

    // 解锁FLASH
    flash_unlock();

    // 状态清除
    flash_flag_clear(FLASH_ODF_FLAG | FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);

    // 开始擦除
    uint8_t u8Ret = flash_sector_erase(u32Addr);

    // 擦除结果
    u8Ret = (u8Ret != FLASH_OPERATE_DONE) ? 1 : 0;

    // 锁定FLASH
    flash_lock(); 

    // 返回结果
    return u8Ret;
}

uint8_t 
bsp_flash_write_byte(uint32_t u32Addr, uint8_t *pu8Buffer, uint32_t u32Len){

    // 判断输入参数是否合法
    if(u32Addr < FLASH_BASE_ADDR || u32Addr + u32Len > FLASH_END_ADDR ||
        NULL == pu8Buffer || 0 == u32Len) return 1;

    // 返回值定义
    uint8_t u8Ret = 0;

    // 解锁FLASH
    flash_unlock();

    // 状态清除
    flash_flag_clear(FLASH_ODF_FLAG | FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);

    // 写入数据
    for(uint32_t i = 0; i < u32Len; i++)
    {
        // 写入数据
        u8Ret = flash_byte_program(u32Addr, pu8Buffer[i]);

        // 判断是否写入成功
        if(u8Ret != FLASH_OPERATE_DONE) break;

        // 地址递增
        u32Addr += 1;
    }

    // 写入结果
    u8Ret = (u8Ret != FLASH_OPERATE_DONE) ? 1 : 0;

    // 锁定FLASH
    flash_lock(); 

    // 返回结果
    return u8Ret;
}

uint8_t 
bsp_flash_write_halfword(uint32_t u32Addr, uint16_t *pu16Buffer, uint32_t u32Len){
    
    // 判断输入参数是否合法
    if(u32Addr < FLASH_BASE_ADDR || u32Addr + u32Len > FLASH_END_ADDR ||
        NULL == pu16Buffer || 0 == u32Len) return 1;

    // 返回值定义
    uint8_t u8Ret = 0;

    // 解锁FLASH
    flash_unlock();

    // 状态清除
    flash_flag_clear(FLASH_ODF_FLAG | FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);

    // 写入数据
    for(uint32_t i = 0; i < u32Len; i++)
    {

        // 交换顺序 -- 低位在前，高位在后
        uint16_t u16Temp = pu16Buffer[i];
        uint16_t u16Low = (u16Temp >> 8) & 0x00FF;
        uint16_t u16High = u16Temp & 0x00FF;
        uint16_t u16Val = (u16High << 8) | u16Low;

        // 写入数据
        u8Ret = flash_halfword_program(u32Addr, u16Val);

        // 判断是否写入成功
        if(u8Ret != FLASH_OPERATE_DONE) break;

        // 地址递增
        u32Addr += 2;
        
    }
    // 写入结果
    u8Ret = (u8Ret != FLASH_OPERATE_DONE) ? 1 : 0;

    // 锁定FLASH
    flash_lock(); 

    // 返回结果
    return u8Ret;
}

uint8_t 
bsp_flash_write_word(uint32_t u32Addr, uint32_t *pu32Buffer, uint32_t u32Len){

    // 判断输入参数是否合法
    if(u32Addr < FLASH_BASE_ADDR || u32Addr + u32Len > FLASH_END_ADDR ||
        NULL == pu32Buffer || 0 == u32Len) return 1;

    // 返回值定义
    uint8_t u8Ret = 0;

    // 解锁FLASH
    flash_unlock();

    // 状态清除
    flash_flag_clear(FLASH_ODF_FLAG | FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);

    // 写入数据
    for(uint32_t i = 0; i < u32Len; i++)
    {

        // 交换顺序 -- 低位在前，高位在后
        uint32_t u32Temp = pu32Buffer[i];
        uint32_t u32Low = (u32Temp >> 24) & 0x000000FF;
        uint32_t u32M2 = (u32Temp >> 16) & 0x000000FF;
        uint32_t u32M1 = (u32Temp >> 8) & 0x000000FF;
        uint32_t u32High = u32Temp & 0x000000FF;
        uint32_t u32Val = u32High << 24 | u32M1 << 16 | u32M2 << 8 | u32Low;

        // 写入数据
        u8Ret = flash_word_program(u32Addr, u32Val);

        // 判断是否写入成功
        if(u8Ret != FLASH_OPERATE_DONE) break;

        // 地址递增
        u32Addr += 4;
        
    }
    // 写入结果
    u8Ret = (u8Ret != FLASH_OPERATE_DONE) ? 1 : 0;

    // 锁定FLASH
    flash_lock(); 

    // 返回结果
    return u8Ret;
}

uint8_t bsp_flash_write(uint32_t u32Addr, uint8_t *pu8Buffer, uint32_t u32Len){

    // flash 扇区缓存
    static uint8_t u8FlashCache[FLASH_SECTOR_SIZE];

    // 结果
    uint8_t u8Ret = 0;

    // 读取一个扇区
    u8Ret = bsp_flash_read_byte(u32Addr, u8FlashCache, FLASH_SECTOR_SIZE);
    if(u8Ret != 0) return u8Ret;

    // 合并数据
    for(uint32_t i = 0; i < u32Len; i++){
        u8FlashCache[i] = pu8Buffer[i];
    }

    // 扇区擦除
    u8Ret = bsp_flash_erase_sector(u32Addr);
    if(u8Ret != 0) return u8Ret;

    // 写入扇区
    u8Ret = bsp_flash_write_byte(u32Addr, u8FlashCache, FLASH_SECTOR_SIZE);
    return u8Ret;
}
  
uint8_t bsp_flash_read(uint32_t u32Addr, uint8_t *pu8Buffer, uint32_t u32Len){
    uint8_t u8Ret = bsp_flash_read_byte(u32Addr, pu8Buffer, u32Len);
    return u8Ret;
}
